Support separators in combo boxes and more generally in tree views
authorMatthias Clasen <mclasen@redhat.com>
Wed, 7 Jul 2004 15:15:35 +0000 (15:15 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Wed, 7 Jul 2004 15:15:35 +0000 (15:15 +0000)
2004-07-07  Matthias Clasen  <mclasen@redhat.com>

Support separators in combo boxes and more generally in tree
views  (#135873):

* gtk/gtkcombobox.h:
* gtk/gtkcombobox.c (gtk_combo_box_get_row_separator_column):
* gtk/gtkcombobox.c (gtk_combo_box_set_row_separator_column):
Add a ::row-separator-column property with getter and setter,
which can indicate a boolean model column to determine which
rows are separators.

* gtk/gtkcombobox.c: Display separator rows as separator menu
items in menu mode, and by using the new treeview separator
functionality in list mode.

* gtk/gtktreeview.h:
* gtk/gtktreeview.c (gtk_tree_view_get_row_separator_func):
* gtk/gtktreeview.c (gtk_tree_view_set_row_separator_func):
Add a callback to determine whether a row is a separator.

* gtk/gtktreeview.c (gtk_tree_view_bin_expose):
* gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon):
* gtk/gtktreeview.c (validate_row): Use the new callback
to determine whether a row is a separator, and draw it
as a separator then. Since separators should take up less
vertical space than regular rows, this requires removing
the redundant MAX(...,expander_size) calls which appear in
many places. Instead, the MAX() is now only done in
validate_row(), and only if the row is not a separator.
To catch possible side effects of this intrusive change,
I have left EXPANDER_MAX() calls in place of the MAX() calls
which will emit a warning if something breaks. They should
be removed before 2.6.

* gtk/gtktreeselection.c (row_is_selectable): Don't let
separator rows be selected.

* tests/testcombo.c (create_blaat): Add a separator column.

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtkcombobox.c
gtk/gtkcombobox.h
gtk/gtktreeselection.c
gtk/gtktreeview.c
gtk/gtktreeview.h
tests/testcombo.c

index 9b3a885c53d2cd3e803c9df8e0e4b0b19834bb22..09c565b98384140eb475a4f456849f58497b5c13 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2004-07-07  Matthias Clasen  <mclasen@redhat.com>
+
+       Support separators in combo boxes and more generally in tree 
+       views  (#135873):
+       
+       * gtk/gtkcombobox.h: 
+       * gtk/gtkcombobox.c (gtk_combo_box_get_row_separator_column):
+       * gtk/gtkcombobox.c (gtk_combo_box_set_row_separator_column):
+       Add a ::row-separator-column property with getter and setter, 
+       which can indicate a boolean model column to determine which
+       rows are separators. 
+
+       * gtk/gtkcombobox.c: Display separator rows as separator menu 
+       items in menu mode, and by using the new treeview separator 
+       functionality in list mode.
+
+       * gtk/gtktreeview.h: 
+       * gtk/gtktreeview.c (gtk_tree_view_get_row_separator_func): 
+       * gtk/gtktreeview.c (gtk_tree_view_set_row_separator_func): 
+       Add a callback to determine whether a row is a separator.
+       
+       * gtk/gtktreeview.c (gtk_tree_view_bin_expose): 
+       * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): 
+       * gtk/gtktreeview.c (validate_row): Use the new callback
+       to determine whether a row is a separator, and draw it
+       as a separator then. Since separators should take up less
+       vertical space than regular rows, this requires removing
+       the redundant MAX(...,expander_size) calls which appear in
+       many places. Instead, the MAX() is now only done in 
+       validate_row(), and only if the row is not a separator.
+       To catch possible side effects of this intrusive change,
+       I have left EXPANDER_MAX() calls in place of the MAX() calls
+       which will emit a warning if something breaks. They should
+       be removed before 2.6.
+
+       * gtk/gtktreeselection.c (row_is_selectable): Don't let 
+       separator rows be selected.
+       
+       * tests/testcombo.c (create_blaat): Add a separator column.
+
 Tue Jul  6 22:58:00 2004  Matthias Clasen  <maclas@gmx.de>
 
        * gdk/x11/gdkwindow-x11.c (gdk_x11_window_set_user_time): Fix
index 9b3a885c53d2cd3e803c9df8e0e4b0b19834bb22..09c565b98384140eb475a4f456849f58497b5c13 100644 (file)
@@ -1,3 +1,43 @@
+2004-07-07  Matthias Clasen  <mclasen@redhat.com>
+
+       Support separators in combo boxes and more generally in tree 
+       views  (#135873):
+       
+       * gtk/gtkcombobox.h: 
+       * gtk/gtkcombobox.c (gtk_combo_box_get_row_separator_column):
+       * gtk/gtkcombobox.c (gtk_combo_box_set_row_separator_column):
+       Add a ::row-separator-column property with getter and setter, 
+       which can indicate a boolean model column to determine which
+       rows are separators. 
+
+       * gtk/gtkcombobox.c: Display separator rows as separator menu 
+       items in menu mode, and by using the new treeview separator 
+       functionality in list mode.
+
+       * gtk/gtktreeview.h: 
+       * gtk/gtktreeview.c (gtk_tree_view_get_row_separator_func): 
+       * gtk/gtktreeview.c (gtk_tree_view_set_row_separator_func): 
+       Add a callback to determine whether a row is a separator.
+       
+       * gtk/gtktreeview.c (gtk_tree_view_bin_expose): 
+       * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): 
+       * gtk/gtktreeview.c (validate_row): Use the new callback
+       to determine whether a row is a separator, and draw it
+       as a separator then. Since separators should take up less
+       vertical space than regular rows, this requires removing
+       the redundant MAX(...,expander_size) calls which appear in
+       many places. Instead, the MAX() is now only done in 
+       validate_row(), and only if the row is not a separator.
+       To catch possible side effects of this intrusive change,
+       I have left EXPANDER_MAX() calls in place of the MAX() calls
+       which will emit a warning if something breaks. They should
+       be removed before 2.6.
+
+       * gtk/gtktreeselection.c (row_is_selectable): Don't let 
+       separator rows be selected.
+       
+       * tests/testcombo.c (create_blaat): Add a separator column.
+
 Tue Jul  6 22:58:00 2004  Matthias Clasen  <maclas@gmx.de>
 
        * gdk/x11/gdkwindow-x11.c (gdk_x11_window_set_user_time): Fix
index 9b3a885c53d2cd3e803c9df8e0e4b0b19834bb22..09c565b98384140eb475a4f456849f58497b5c13 100644 (file)
@@ -1,3 +1,43 @@
+2004-07-07  Matthias Clasen  <mclasen@redhat.com>
+
+       Support separators in combo boxes and more generally in tree 
+       views  (#135873):
+       
+       * gtk/gtkcombobox.h: 
+       * gtk/gtkcombobox.c (gtk_combo_box_get_row_separator_column):
+       * gtk/gtkcombobox.c (gtk_combo_box_set_row_separator_column):
+       Add a ::row-separator-column property with getter and setter, 
+       which can indicate a boolean model column to determine which
+       rows are separators. 
+
+       * gtk/gtkcombobox.c: Display separator rows as separator menu 
+       items in menu mode, and by using the new treeview separator 
+       functionality in list mode.
+
+       * gtk/gtktreeview.h: 
+       * gtk/gtktreeview.c (gtk_tree_view_get_row_separator_func): 
+       * gtk/gtktreeview.c (gtk_tree_view_set_row_separator_func): 
+       Add a callback to determine whether a row is a separator.
+       
+       * gtk/gtktreeview.c (gtk_tree_view_bin_expose): 
+       * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): 
+       * gtk/gtktreeview.c (validate_row): Use the new callback
+       to determine whether a row is a separator, and draw it
+       as a separator then. Since separators should take up less
+       vertical space than regular rows, this requires removing
+       the redundant MAX(...,expander_size) calls which appear in
+       many places. Instead, the MAX() is now only done in 
+       validate_row(), and only if the row is not a separator.
+       To catch possible side effects of this intrusive change,
+       I have left EXPANDER_MAX() calls in place of the MAX() calls
+       which will emit a warning if something breaks. They should
+       be removed before 2.6.
+
+       * gtk/gtktreeselection.c (row_is_selectable): Don't let 
+       separator rows be selected.
+       
+       * tests/testcombo.c (create_blaat): Add a separator column.
+
 Tue Jul  6 22:58:00 2004  Matthias Clasen  <maclas@gmx.de>
 
        * gdk/x11/gdkwindow-x11.c (gdk_x11_window_set_user_time): Fix
index 9b3a885c53d2cd3e803c9df8e0e4b0b19834bb22..09c565b98384140eb475a4f456849f58497b5c13 100644 (file)
@@ -1,3 +1,43 @@
+2004-07-07  Matthias Clasen  <mclasen@redhat.com>
+
+       Support separators in combo boxes and more generally in tree 
+       views  (#135873):
+       
+       * gtk/gtkcombobox.h: 
+       * gtk/gtkcombobox.c (gtk_combo_box_get_row_separator_column):
+       * gtk/gtkcombobox.c (gtk_combo_box_set_row_separator_column):
+       Add a ::row-separator-column property with getter and setter, 
+       which can indicate a boolean model column to determine which
+       rows are separators. 
+
+       * gtk/gtkcombobox.c: Display separator rows as separator menu 
+       items in menu mode, and by using the new treeview separator 
+       functionality in list mode.
+
+       * gtk/gtktreeview.h: 
+       * gtk/gtktreeview.c (gtk_tree_view_get_row_separator_func): 
+       * gtk/gtktreeview.c (gtk_tree_view_set_row_separator_func): 
+       Add a callback to determine whether a row is a separator.
+       
+       * gtk/gtktreeview.c (gtk_tree_view_bin_expose): 
+       * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): 
+       * gtk/gtktreeview.c (validate_row): Use the new callback
+       to determine whether a row is a separator, and draw it
+       as a separator then. Since separators should take up less
+       vertical space than regular rows, this requires removing
+       the redundant MAX(...,expander_size) calls which appear in
+       many places. Instead, the MAX() is now only done in 
+       validate_row(), and only if the row is not a separator.
+       To catch possible side effects of this intrusive change,
+       I have left EXPANDER_MAX() calls in place of the MAX() calls
+       which will emit a warning if something breaks. They should
+       be removed before 2.6.
+
+       * gtk/gtktreeselection.c (row_is_selectable): Don't let 
+       separator rows be selected.
+       
+       * tests/testcombo.c (create_blaat): Add a separator column.
+
 Tue Jul  6 22:58:00 2004  Matthias Clasen  <maclas@gmx.de>
 
        * gdk/x11/gdkwindow-x11.c (gdk_x11_window_set_user_time): Fix
index 613b12f9342d172d106dbad1620f355e0dca7453..b08515dff96dd0340d38396076123d53c3b33d90 100644 (file)
@@ -32,6 +32,7 @@
 #include "gtkliststore.h"
 #include "gtkmain.h"
 #include "gtkmenu.h"
+#include "gtkseparatormenuitem.h"
 #include "gtktearoffmenuitem.h"
 #include "gtktogglebutton.h"
 #include "gtktreeselection.h"
@@ -73,6 +74,7 @@ struct _GtkComboBoxPrivate
 
   gint col_column;
   gint row_column;
+  gint separator_column;
 
   gint wrap_width;
 
@@ -171,6 +173,7 @@ enum {
   PROP_WRAP_WIDTH,
   PROP_ROW_SPAN_COLUMN,
   PROP_COLUMN_SPAN_COLUMN,
+  PROP_ROW_SEPARATOR_COLUMN,
   PROP_ACTIVE,
   PROP_ADD_TEAROFFS
 };
@@ -482,9 +485,9 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
                                    g_param_spec_int ("row_span_column",
                                                      P_("Row span column"),
                                                      P_("TreeModel column containing the row span values"),
-                                                     0,
+                                                     -1,
                                                      G_MAXINT,
-                                                     0,
+                                                     -1,
                                                      G_PARAM_READWRITE));
 
   g_object_class_install_property (object_class,
@@ -492,9 +495,19 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
                                    g_param_spec_int ("column_span_column",
                                                      P_("Column span column"),
                                                      P_("TreeModel column containing the column span values"),
-                                                     0,
+                                                     -1,
                                                      G_MAXINT,
-                                                     0,
+                                                     -1,
+                                                     G_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_ROW_SEPARATOR_COLUMN,
+                                   g_param_spec_int ("row_separator_column",
+                                                     P_("Row separator column"),
+                                                     P_("Boolean TreeModel column specifying which rows are separators"),
+                                                     -1,
+                                                     G_MAXINT,
+                                                     -1,
                                                      G_PARAM_READWRITE));
 
   g_object_class_install_property (object_class,
@@ -563,6 +576,7 @@ gtk_combo_box_init (GtkComboBox *combo_box)
   combo_box->priv->active_item = -1;
   combo_box->priv->col_column = -1;
   combo_box->priv->row_column = -1;
+  combo_box->priv->separator_column = -1;
 }
 
 static void
@@ -591,6 +605,10 @@ gtk_combo_box_set_property (GObject      *object,
         gtk_combo_box_set_column_span_column (combo_box, g_value_get_int (value));
         break;
 
+      case PROP_ROW_SEPARATOR_COLUMN:
+        gtk_combo_box_set_row_separator_column (combo_box, g_value_get_int (value));
+        break;
+
       case PROP_ACTIVE:
         gtk_combo_box_set_active (combo_box, g_value_get_int (value));
         break;
@@ -630,6 +648,10 @@ gtk_combo_box_get_property (GObject    *object,
         g_value_set_int (value, combo_box->priv->col_column);
         break;
 
+      case PROP_ROW_SEPARATOR_COLUMN:
+        g_value_set_int (value, combo_box->priv->separator_column);
+        break;
+
       case PROP_ACTIVE:
         g_value_set_int (value, gtk_combo_box_get_active (combo_box));
         break;
@@ -1153,7 +1175,10 @@ menu_row_is_sensitive (GtkComboBox *combo_box,
   GtkWidget *cell_view;
   GList *cells, *list;
   gboolean sensitive;
-
+  
+  if (!GTK_IS_CELL_VIEW_MENU_ITEM (item))
+    return FALSE;
+    
   cell_view = gtk_bin_get_child (GTK_BIN (item));
   
   gtk_cell_view_set_cell_data (GTK_CELL_VIEW (cell_view));
@@ -1186,6 +1211,19 @@ tree_column_row_is_sensitive (GtkComboBox *combo_box,
   if (!combo_box->priv->column)
     return TRUE;
 
+  if (combo_box->priv->separator_column != -1)
+    {
+      gboolean is_separator;
+
+      gtk_tree_model_get (combo_box->priv->model,
+                         iter,
+                         combo_box->priv->separator_column, &is_separator,
+                         -1);
+
+      if (is_separator)
+       return FALSE;
+    }
+
   gtk_tree_view_column_cell_set_cell_data (combo_box->priv->column,
                                           combo_box->priv->model,
                                           iter, FALSE, FALSE);
@@ -1266,14 +1304,14 @@ update_menu_sensitivity (GtkComboBox *combo_box)
   children = gtk_container_get_children (GTK_CONTAINER (menu));
   child = children;
 
-  if (child && GTK_IS_TEAROFF_MENU_ITEM (child->data))
-    child = child->next;
-
   for (i = 0; i < items; i++, child = child->next)
     {
       GtkWidget *item = GTK_WIDGET (child->data);
       gboolean sensitive;
 
+      if (!GTK_IS_CELL_VIEW_MENU_ITEM (item))
+       continue;
+
       sensitive = menu_row_is_sensitive (combo_box, item);
       gtk_widget_set_sensitive (item, sensitive);
     }
@@ -1327,7 +1365,7 @@ gtk_combo_box_popup (GtkComboBox *combo_box)
 
   gtk_widget_show_all (combo_box->priv->popup_frame);
   gtk_combo_box_list_position (combo_box, &x, &y, &width, &height);
-
+  
   gtk_widget_set_size_request (combo_box->priv->popup_window, width, -1);  
   gtk_window_move (GTK_WINDOW (combo_box->priv->popup_window), x, y);
 
@@ -1378,6 +1416,7 @@ gtk_combo_box_popdown (GtkComboBox *combo_box)
     }
 
   gtk_combo_box_list_remove_grabs (combo_box);
+
   gtk_widget_hide_all (combo_box->priv->popup_window);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (combo_box->priv->button),
                                 FALSE);
@@ -1755,8 +1794,7 @@ gtk_combo_box_scroll_event (GtkWidget          *widget,
                             GdkEventScroll     *event)
 {
   GtkComboBox *combo_box = GTK_COMBO_BOX (widget);
-  gint index;
-  gint items;
+  gint index, new_index, items;
     
   index = gtk_combo_box_get_active (combo_box);
 
@@ -1765,11 +1803,23 @@ gtk_combo_box_scroll_event (GtkWidget          *widget,
       items = gtk_tree_model_iter_n_children (combo_box->priv->model, NULL);
       
       if (event->direction == GDK_SCROLL_UP)
-        index--;
-      else 
-        index++;
+       {
+         new_index = index - 1;
+         while (new_index >= 0 && !row_is_sensitive (combo_box, new_index))
+           new_index--;
+         if (new_index < 0)
+           new_index = index;
+       }
+      else
+       {
+         new_index = index + 1;
+         while (new_index < items && !row_is_sensitive (combo_box, new_index))
+           new_index++;
+         if (new_index == items)
+           new_index = index;
+       }
 
-      gtk_combo_box_set_active (combo_box, CLAMP (index, 0, items - 1));
+      gtk_combo_box_set_active (combo_box, CLAMP (new_index, 0, items - 1));
     }
 
   return TRUE;
@@ -1905,16 +1955,33 @@ gtk_combo_box_menu_fill (GtkComboBox *combo_box)
   for (i = 0; i < items; i++)
     {
       GtkTreePath *path;
+      GtkTreeIter iter;
+      gboolean is_separator;
 
       path = gtk_tree_path_new_from_indices (i, -1);
-      tmp = gtk_cell_view_menu_item_new_from_model (combo_box->priv->model,
-                                                    path);
-      g_signal_connect (tmp, "activate",
-                        G_CALLBACK (gtk_combo_box_menu_item_activate),
-                        combo_box);
 
-      cell_view_sync_cells (combo_box,
-                            GTK_CELL_VIEW (GTK_BIN (tmp)->child));
+      if (combo_box->priv->separator_column != -1)
+       {
+         gtk_tree_model_get_iter (combo_box->priv->model, &iter, path);
+         gtk_tree_model_get (combo_box->priv->model, &iter, 
+                             combo_box->priv->separator_column, &is_separator, -1);
+       }
+      else
+       is_separator = FALSE;
+
+      if (is_separator)
+       tmp = gtk_separator_menu_item_new ();
+      else
+       {
+         tmp = gtk_cell_view_menu_item_new_from_model (combo_box->priv->model,
+                                                       path);
+         g_signal_connect (tmp, "activate",
+                           G_CALLBACK (gtk_combo_box_menu_item_activate),
+                           combo_box);
+         
+         cell_view_sync_cells (combo_box,
+                               GTK_CELL_VIEW (GTK_BIN (tmp)->child));
+       }
 
       gtk_menu_shell_append (GTK_MENU_SHELL (menu), tmp);
 
@@ -2345,6 +2412,21 @@ gtk_combo_box_menu_row_changed (GtkTreeModel *model,
  * list style
  */
 
+static gboolean
+row_is_separator (GtkTreeModel      *model,
+                 GtkTreeIter       *iter,
+                 gpointer           data)
+{
+  GtkComboBox *combo_box = GTK_COMBO_BOX (data);
+  gboolean is_separator = FALSE;
+
+  if (combo_box->priv->separator_column != -1)
+    gtk_tree_model_get (combo_box->priv->model, iter, 
+                       combo_box->priv->separator_column, &is_separator, -1);
+
+  return is_separator;
+}
+
 static void
 gtk_combo_box_list_setup (GtkComboBox *combo_box)
 {
@@ -2399,7 +2481,8 @@ gtk_combo_box_list_setup (GtkComboBox *combo_box)
                                      FALSE);
   gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (combo_box->priv->tree_view),
                                     TRUE);
-
+  gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (combo_box->priv->tree_view),
+                                       row_is_separator, combo_box, NULL);
   if (combo_box->priv->model)
     gtk_tree_view_set_model (GTK_TREE_VIEW (combo_box->priv->tree_view),
                             combo_box->priv->model);
@@ -3303,7 +3386,7 @@ gtk_combo_box_set_row_span_column (GtkComboBox *combo_box,
   g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
 
   col = gtk_tree_model_get_n_columns (combo_box->priv->model);
-  g_return_if_fail (row_span >= 0 && row_span < col);
+  g_return_if_fail (row_span >= -1 && row_span < col);
 
   if (row_span != combo_box->priv->row_column)
     {
@@ -3353,7 +3436,7 @@ gtk_combo_box_set_column_span_column (GtkComboBox *combo_box,
   g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
 
   col = gtk_tree_model_get_n_columns (combo_box->priv->model);
-  g_return_if_fail (column_span >= 0 && column_span < col);
+  g_return_if_fail (column_span >= -1 && column_span < col);
 
   if (column_span != combo_box->priv->col_column)
     {
@@ -3876,3 +3959,54 @@ gtk_combo_box_set_add_tearoffs (GtkComboBox *combo_box,
       g_object_notify (G_OBJECT (combo_box), "add_tearoffs");
     }
 }
+
+/**
+ * gtk_combo_box_set_row_separator_column:
+ * @combo_box: a #GtkComboBox
+ * @column: the index of a boolean model column, or -1 to 
+ *   turn off separators
+ * 
+ * Sets the row separator column index. 
+ * This model column contains boolean values which indicate 
+ * whether a row is to be drawn as a separator or now. 
+ * Setting the index to -1 turns off separators.
+ *
+ * Since: 2.6
+ **/
+void
+gtk_combo_box_set_row_separator_column (GtkComboBox *combo_box,
+                                       gint         column)
+{
+  gint col;
+
+  g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
+  col = gtk_tree_model_get_n_columns (combo_box->priv->model);
+  g_return_if_fail (column >= -1 && column < col);
+
+  if (combo_box->priv->separator_column != column)
+    {
+      combo_box->priv->separator_column = column;
+
+      gtk_widget_queue_draw (combo_box);
+
+      g_object_notify (G_OBJECT (combo_box), "row_separator_column");
+    }
+}
+
+/**
+ * gtk_combo_box_get_row_separator_column:
+ * @combo_box: a #GtkComboBox
+ * 
+ * Returns the current row separator column index.
+ * 
+ * Return value: the row separator column index
+ *
+ * Since: 2.6
+ **/
+gint
+gtk_combo_box_get_row_separator_column (GtkComboBox *combo_box)
+{
+  g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), -1);
+
+  return combo_box->priv->separator_column;
+}
index 7ecccbfd743ddb23130772342fb3e2c0ab2587a0..4d6b3e460f3ffcce5b4066cf980cf4535ebc9ccd 100644 (file)
@@ -94,6 +94,10 @@ void          gtk_combo_box_set_model        (GtkComboBox     *combo_box,
                                               GtkTreeModel    *model);
 GtkTreeModel *gtk_combo_box_get_model        (GtkComboBox     *combo_box);
 
+void          gtk_combo_box_set_row_separator_column (GtkComboBox *combo_box,
+                                                     gint         column);
+gint          gtk_combo_box_get_row_separator_column (GtkComboBox *combo_box);
+
 /* convenience -- text */
 GtkWidget    *gtk_combo_box_new_text         (void);
 void          gtk_combo_box_append_text      (GtkComboBox     *combo_box,
index 4e5a76a7da78d1356ad2646d6126ff0465f34a8c..b8ac48b8b8c20f105307734456f675f0db6b0963 100644 (file)
@@ -1319,21 +1319,29 @@ row_is_selectable (GtkTreeSelection *selection,
                   GtkTreePath      *path)
 {
   GList *list;
-  gboolean sensitive;
-  
-  sensitive = FALSE;
+  GtkTreeIter iter;
+  gboolean sensitive = FALSE;
+
+  if (!gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path))
+    sensitive = TRUE;
+
+  if (!sensitive && selection->tree_view->priv->row_separator_func)
+    {
+      /* never allow separators to be selected */
+      if ((* selection->tree_view->priv->row_separator_func) (selection->tree_view->priv->model,
+                                                             &iter,
+                                                             selection->tree_view->priv->row_separator_data))
+       return FALSE;
+    }
+
   for (list = selection->tree_view->priv->columns; list && !sensitive; list = list->next)
     {
       GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
-      GtkTreeIter iter;
 
       if (!column->visible)
        continue;
 
-      if (gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path))
-       sensitive = tree_column_is_sensitive (column, selection->tree_view->priv->model, &iter);
-      else
-       sensitive = TRUE;
+      sensitive = tree_column_is_sensitive (column, selection->tree_view->priv->model, &iter);
     }
 
   if (!sensitive)
index c126658a18f3238b6a5453fc2179786025d69b02..217b78dd9c73a0137b2a51ebdd1e9ab5c612ad65 100644 (file)
@@ -62,6 +62,8 @@
 #define BACKGROUND_FIRST_PIXEL(tree_view,tree,node) (RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, _gtk_rbtree_node_find_offset ((tree), (node))))
 #define CELL_FIRST_PIXEL(tree_view,tree,node,separator) (BACKGROUND_FIRST_PIXEL (tree_view,tree,node) + separator/2)
 
+#define EXPANDER_MAX(height,expander_size,tree_view,tree,node) check_expander_max (height, expander_size, tree_view, tree, node)
+
 
 typedef struct _GtkTreeViewChild GtkTreeViewChild;
 struct _GtkTreeViewChild
@@ -423,6 +425,12 @@ static void gtk_tree_view_tree_window_to_tree_coords (GtkTreeView *tree_view,
                                                      gint         wy,
                                                      gint        *tx,
                                                      gint        *ty);
+static gint check_expander_max (gint height,
+                               gint expander_size,
+                               GtkTreeView *tree_view,
+                               GtkRBTree   *tree,
+                               GtkRBNode   *node);
+
 
 static GtkContainerClass *parent_class = NULL;
 static guint tree_view_signals [LAST_SIGNAL] = { 0 };
@@ -1346,6 +1354,12 @@ gtk_tree_view_destroy (GtkObject *object)
       tree_view->priv->search_user_data = NULL;
     }
 
+  if (tree_view->priv->row_separator_destroy)
+    {
+      (* tree_view->priv->row_separator_destroy) (tree_view->priv->row_separator_data);
+      tree_view->priv->row_separator_data = NULL;
+    }
+  
   gtk_tree_view_set_model (tree_view, NULL);
 
   if (GTK_OBJECT_CLASS (parent_class)->destroy)
@@ -2155,8 +2169,9 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       path = _gtk_tree_view_find_path (tree_view, tree, node);
       depth = gtk_tree_path_get_depth (path);
       background_area.y = y_offset + event->y;
-      background_area.height = MAX (GTK_RBNODE_GET_HEIGHT (node),
-                                   tree_view->priv->expander_size);
+      background_area.height = EXPANDER_MAX (GTK_RBNODE_GET_HEIGHT (node),
+                                            tree_view->priv->expander_size, 
+                                            tree_view, tree, node);
       background_area.x = 0;
 
 
@@ -2621,7 +2636,8 @@ coords_are_over_arrow (GtkTreeView *tree_view,
 
   arrow.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
 
-  arrow.height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
+  arrow.height = EXPANDER_MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size,
+                              tree_view, tree, node);
 
   gtk_tree_view_get_arrow_xrange (tree_view, tree, &arrow.x, &x2);
 
@@ -3309,7 +3325,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                           path);
   depth = gtk_tree_path_get_depth (path);
   gtk_tree_path_free (path);
-
+  
   cursor_path = NULL;
   drag_dest_path = NULL;
 
@@ -3330,7 +3346,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   gdk_drawable_get_size (tree_view->priv->bin_window,
                          &bin_window_width, NULL);
 
-
+  
   n_visible_columns = 0;
   for (list = tree_view->priv->columns; list; list = list->next)
     {
@@ -3355,8 +3371,17 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   do
     {
       gboolean parity;
+      gboolean is_separator = FALSE;
+      
+      if (tree_view->priv->row_separator_func)
+       {
+         is_separator = (* tree_view->priv->row_separator_func) (tree_view->priv->model,
+                                                                 &iter,
+                                                                 tree_view->priv->row_separator_data);
+       }
 
-      max_height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
+      max_height = EXPANDER_MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size, 
+                                tree_view, tree, node);
 
       x_offset = -event->area.x;
       cell_offset = 0;
@@ -3499,12 +3524,23 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                * level of the tree we're dropping at.
                */
               highlight_x = cell_area.x;
-             _gtk_tree_view_column_cell_render (column,
-                                                event->window,
-                                                &background_area,
-                                                &cell_area,
-                                                &event->area,
-                                                flags);
+             if (is_separator)
+               gtk_paint_hline (widget->style,
+                                event->window,
+                                state,
+                                &cell_area,
+                                widget,
+                                NULL,
+                                cell_area.x,
+                                cell_area.x + cell_area.width,
+                                cell_area.y + cell_area.height / 2);
+             else
+               _gtk_tree_view_column_cell_render (column,
+                                                  event->window,
+                                                  &background_area,
+                                                  &cell_area,
+                                                  &event->area,
+                                                  flags);
              if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
                {
                  gint x, y;
@@ -3517,12 +3553,23 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
            }
          else
            {
-             _gtk_tree_view_column_cell_render (column,
-                                                event->window,
-                                                &background_area,
-                                                &cell_area,
-                                                &event->area,
-                                                flags);
+             if (is_separator)
+               gtk_paint_hline (widget->style,
+                                event->window,
+                                state,
+                                &cell_area,
+                                widget,
+                                NULL,
+                                cell_area.x,
+                                cell_area.x + cell_area.width,
+                                cell_area.y + cell_area.height / 2);
+             else
+               _gtk_tree_view_column_cell_render (column,
+                                                  event->window,
+                                                  &background_area,
+                                                  &cell_area,
+                                                  &event->area,
+                                                  flags);
            }
          if (node == cursor && has_special_cell &&
              ((column == tree_view->priv->focus_column &&
@@ -3579,8 +3626,9 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                               "treeview-drop-indicator",
                               0, BACKGROUND_FIRST_PIXEL (tree_view, tree, node)
                               - focus_line_width / 2,
-                              width, MAX(BACKGROUND_HEIGHT (node),
-                                         tree_view->priv->expander_size)
+                              width, EXPANDER_MAX(BACKGROUND_HEIGHT (node),
+                                                  tree_view->priv->expander_size, 
+                                                  tree_view, tree, node)
                               - focus_line_width + 1);
               break;
             }
@@ -3621,8 +3669,9 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                           0,
                           BACKGROUND_FIRST_PIXEL (tree_view, tree, node),
                           width,
-                          MAX (BACKGROUND_HEIGHT (node),
-                               tree_view->priv->expander_size));
+                          EXPANDER_MAX (BACKGROUND_HEIGHT (node),
+                                        tree_view->priv->expander_size,
+                                        tree_view, tree, node));
        }
 
       y_offset += max_height;
@@ -4265,16 +4314,26 @@ validate_row (GtkTreeView *tree_view,
   gint horizontal_separator;
   gint depth = gtk_tree_path_get_depth (path);
   gboolean retval = FALSE;
-
+  gboolean is_separator = FALSE;
+  gint focus_pad;
+      
   /* double check the row needs validating */
   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) &&
       ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
     return FALSE;
 
+  if (tree_view->priv->row_separator_func)
+    {
+      is_separator = (* tree_view->priv->row_separator_func) (tree_view->priv->model,
+                                                             iter,
+                                                             tree_view->priv->row_separator_data);
+    }
+
   gtk_widget_style_get (GTK_WIDGET (tree_view),
+                       "focus-padding", &focus_pad,
                        "horizontal_separator", &horizontal_separator,
                        NULL);
-
+  
   for (list = tree_view->priv->columns; list; list = list->next)
     {
       gint tmp_width;
@@ -4295,8 +4354,13 @@ validate_row (GtkTreeView *tree_view,
                                          NULL, NULL, NULL,
                                          &tmp_width, &tmp_height);
 
-      height = MAX (height, tmp_height);
-      height = MAX (height, tree_view->priv->expander_size);
+      if (!is_separator)
+       {
+         height = MAX (height, tmp_height);
+         height = MAX (height, tree_view->priv->expander_size);
+       }
+      else
+       height = 2 + 2 * focus_pad;
 
       if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view))
         {
@@ -4368,7 +4432,8 @@ validate_visible_area (GtkTreeView *tree_view)
 
          if (tree_view->priv->scroll_to_use_align)
            {
-             gint height = MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+             gint height = EXPANDER_MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size,
+                                         tree_view, tree, node);
              area_above = (total_height - height) *
                tree_view->priv->scroll_to_row_align;
              area_below = total_height - area_above - height;
@@ -4382,7 +4447,8 @@ validate_visible_area (GtkTreeView *tree_view)
               * 2) row visible
               */
              gint dy;
-             gint height = MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+             gint height = EXPANDER_MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size, 
+                                         tree_view, tree, node);
 
              dy = _gtk_rbtree_node_find_offset (tree, node);
 
@@ -4481,7 +4547,8 @@ validate_visible_area (GtkTreeView *tree_view)
            size_changed = TRUE;
        }
       area_above = 0;
-      area_below = total_height - MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+      area_below = total_height - EXPANDER_MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size,
+                                               tree_view, tree, node);
     }
 
   above_path = gtk_tree_path_copy (path);
@@ -4569,7 +4636,8 @@ validate_visible_area (GtkTreeView *tree_view)
             }
        }
 
-      area_below -= MAX (new_height, tree_view->priv->expander_size);
+      area_below -= EXPANDER_MAX (new_height, tree_view->priv->expander_size,
+                                 tree_view, tree, node);
     }
   gtk_tree_path_free (path);
 
@@ -4612,7 +4680,8 @@ validate_visible_area (GtkTreeView *tree_view)
               area_above -= new_height - old_height;
             }
        }
-      area_above -= MAX (new_height, tree_view->priv->expander_size);
+      area_above -= EXPANDER_MAX (new_height, tree_view->priv->expander_size,
+                                 tree_view, tree, node);
       update_dy = TRUE;
     }
 
@@ -4701,8 +4770,9 @@ initialize_fixed_height_mode (GtkTreeView *tree_view)
 
       gtk_tree_path_free (path);
 
-      tree_view->priv->fixed_height = MAX (GTK_RBNODE_GET_HEIGHT (node),
-                                           tree_view->priv->expander_size);
+      tree_view->priv->fixed_height = EXPANDER_MAX (GTK_RBNODE_GET_HEIGHT (node),
+                                                   tree_view->priv->expander_size,
+                                                   tree_view, tree, node);
     }
 
    _gtk_rbtree_set_fixed_height (tree_view->priv->tree,
@@ -4810,7 +4880,8 @@ do_validate_rows (GtkTreeView *tree_view)
         {
          gint height;
 
-         height = MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+         height = EXPANDER_MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size,
+                                tree_view, tree, node);
          if (prev_height < 0)
            prev_height = height;
          else if (prev_height != height)
@@ -5025,7 +5096,8 @@ gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view)
       return;
     }
 
-  if (MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size)
+  if (EXPANDER_MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size,
+                   tree_view, tree, node)
       < tree_view->priv->top_row_dy)
     {
       /* new top row -- do NOT install the idle handler */
@@ -7927,7 +7999,8 @@ gtk_tree_view_queue_draw_arrow (GtkTreeView      *tree_view,
   rect.width = MAX (tree_view->priv->expander_size, GTK_WIDGET (tree_view)->allocation.width);
 
   rect.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
-  rect.height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
+  rect.height = EXPANDER_MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size,
+                             tree_view, tree, node);
 
   if (clip_rect)
     {
@@ -7958,7 +8031,8 @@ _gtk_tree_view_queue_draw_node (GtkTreeView  *tree_view,
   rect.width = MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width);
 
   rect.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
-  rect.height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
+  rect.height = EXPANDER_MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size,
+                             tree_view, tree, node);
 
   if (clip_rect)
     {
@@ -8183,11 +8257,13 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
   y = _gtk_rbtree_node_find_offset (cursor_tree, cursor_node);
   y += count * tree_view->priv->vadjustment->page_size;
   if (count > 0)
-    y -= MAX (GTK_RBNODE_GET_HEIGHT (cursor_node),
-             tree_view->priv->expander_size);
+    y -= EXPANDER_MAX (GTK_RBNODE_GET_HEIGHT (cursor_node), 
+                      tree_view->priv->expander_size,
+                      tree_view, cursor_tree, cursor_node);
   else if (count < 0)
-    y += MAX (GTK_RBNODE_GET_HEIGHT (cursor_node),
-             tree_view->priv->expander_size);
+    y += EXPANDER_MAX (GTK_RBNODE_GET_HEIGHT (cursor_node),
+                      tree_view->priv->expander_size,
+                      tree_view, cursor_tree, cursor_node);
   y = CLAMP (y, (gint)tree_view->priv->vadjustment->lower,  (gint)tree_view->priv->vadjustment->upper - vertical_separator);
 
   if (y > tree_view->priv->height)
@@ -10999,7 +11075,8 @@ gtk_tree_view_get_background_area (GtkTreeView        *tree_view,
 
       rect->y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
 
-      rect->height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
+      rect->height = EXPANDER_MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size,
+                                  tree_view, tree, node);
     }
 
   if (column)
@@ -11492,6 +11569,7 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
   gint x = 1, y = 1;
   GdkDrawable *drawable;
   gint bin_window_width;
+  gboolean is_separator = FALSE;
 
   widget = GTK_WIDGET (tree_view);
 
@@ -11509,11 +11587,19 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
                                 &iter,
                                 path))
     return NULL;
+  
+  if (tree_view->priv->row_separator_func)
+    {
+      is_separator = (* tree_view->priv->row_separator_func) (tree_view->priv->model,
+                                                             &iter,
+                                                             tree_view->priv->row_separator_data);
+    }
 
   cell_offset = x;
 
   background_area.y = y;
-  background_area.height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
+  background_area.height = EXPANDER_MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size,
+                                        tree_view, tree, node);
 
   gdk_drawable_get_size (tree_view->priv->bin_window,
                          &bin_window_width, NULL);
@@ -11565,12 +11651,25 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
         }
 
       if (gtk_tree_view_column_cell_is_visible (column))
-       _gtk_tree_view_column_cell_render (column,
-                                          drawable,
-                                          &background_area,
-                                          &cell_area,
-                                          &expose_area,
-                                          0);
+       {
+         if (is_separator)
+           gtk_paint_hline (widget->style,
+                            drawable,
+                            GTK_STATE_NORMAL,
+                            &cell_area,
+                            widget,
+                            NULL,
+                            cell_area.x,
+                            cell_area.x + cell_area.width,
+                            cell_area.y + cell_area.height / 2);
+         else
+           _gtk_tree_view_column_cell_render (column,
+                                              drawable,
+                                              &background_area,
+                                              &cell_area,
+                                              &expose_area,
+                                              0);
+       }
       cell_offset += column->width;
     }
 
@@ -12338,3 +12437,85 @@ gtk_tree_view_get_hover_selection (GtkTreeView *tree_view)
 {
   return tree_view->priv->hover_selection;
 }
+
+
+/**
+ * gtk_tree_view_get_row_separator_func:
+ * @tree_view: a #GtkTreeView
+ * 
+ * Returns the current row separator function.
+ * 
+ * Return value: the current row separator function.
+ *
+ * Since: 2.6
+ **/
+GtkTreeViewRowSeparatorFunc 
+gtk_tree_view_get_row_separator_func (GtkTreeView *tree_view)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
+
+  return tree_view->priv->row_separator_func;
+}
+
+/**
+ * gtk_tree_view_set_row_separator_func:
+ * @tree_view: a #GtkTreeView
+ * @func: a #GtkTreeRowSeparatorFunc
+ * @data: user data to pass to @func, or %NULL
+ * @destroy: destroy notifier for @data, or %NULL
+ * 
+ * Sets the row separator function, which is used to determine
+ * whether a row should be drawn as a separator.
+ *
+ * Since: 2.6
+ **/
+void
+gtk_tree_view_set_row_separator_func (GtkTreeView                *tree_view,
+                                     GtkTreeViewRowSeparatorFunc func,
+                                     gpointer                    data,
+                                     GtkDestroyNotify            destroy)
+{
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+  if (tree_view->priv->row_separator_destroy)
+    (* tree_view->priv->row_separator_destroy) (tree_view->priv->row_separator_data);
+
+  tree_view->priv->row_separator_func = func;
+  tree_view->priv->row_separator_data = data;
+  tree_view->priv->row_separator_destroy = destroy;
+}
+
+static gint
+check_expander_max (gint height,
+                   gint expander_size,
+                   GtkTreeView *tree_view,
+                   GtkRBTree   *tree,
+                   GtkRBNode   *node)
+{
+  if (height < expander_size)
+    {
+      gboolean is_separator = FALSE;
+
+      if (tree_view->priv->row_separator_func)
+       {
+         GtkTreePath *path;
+         GtkTreeIter iter;
+
+         path = _gtk_tree_view_find_path (tree_view, tree, node);
+         gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);      
+         gtk_tree_path_free (path);
+
+         is_separator = (* tree_view->priv->row_separator_func) (tree_view->priv->model,
+                                                                 &iter,
+                                                                 tree_view->priv->row_separator_data);
+       }
+      
+      if (!is_separator)
+       g_warning ("height less than expander size;\n"
+                  "please report this in http://bugzilla.gnome.org/show_bug.cgi?id=145528\n");
+    }
+  
+  return height;
+}
+  
+
index 85baf95e06288c97960f4b71f74dc57a55cc2010..d0f59174a9548b51b6a63ab9355fdadbe7d613aa 100644 (file)
@@ -124,6 +124,9 @@ typedef gboolean (*GtkTreeViewSearchEqualFunc) (GtkTreeModel            *model,
                                                const gchar             *key,
                                                GtkTreeIter             *iter,
                                                gpointer                 search_data);
+typedef gboolean (*GtkTreeViewRowSeparatorFunc) (GtkTreeModel      *model,
+                                                GtkTreeIter       *iter,
+                                                gpointer           data);
 
 
 /* Creators */
@@ -320,6 +323,12 @@ void     gtk_tree_view_set_hover_selection   (GtkTreeView          *tree_view,
                                              gboolean              hover);
 gboolean gtk_tree_view_get_hover_selection   (GtkTreeView          *tree_view);
 
+GtkTreeViewRowSeparatorFunc gtk_tree_view_get_row_separator_func (GtkTreeView               *tree_view);
+void                        gtk_tree_view_set_row_separator_func (GtkTreeView                *tree_view,
+                                                                 GtkTreeViewRowSeparatorFunc func,
+                                                                 gpointer                    data,
+                                                                 GtkDestroyNotify            destroy);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index 157963d5836a4ffdc78def4e14d1007e25909b0d..b26f8ca50c85dbeae794fb0b8ea7a74ba9ac921b 100644 (file)
@@ -127,7 +127,7 @@ create_blaat ()
 
         cellview = gtk_cell_view_new ();
 
-        store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
+        store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_BOOLEAN);
 
         pixbuf = gtk_widget_render_icon (cellview, GTK_STOCK_DIALOG_WARNING,
                                          GTK_ICON_SIZE_BUTTON, NULL);
@@ -135,6 +135,7 @@ create_blaat ()
         gtk_list_store_set (store, &iter,
                             0, pixbuf,
                             1, "gtk-stock-dialog-warning",
+                           2, FALSE,
                             -1);
 
         pixbuf = gtk_widget_render_icon (cellview, GTK_STOCK_STOP,
@@ -143,6 +144,7 @@ create_blaat ()
         gtk_list_store_set (store, &iter,
                             0, pixbuf,
                             1, "gtk-stock-stop",
+                           2, FALSE,
                             -1);
 
         pixbuf = gtk_widget_render_icon (cellview, GTK_STOCK_NEW,
@@ -151,6 +153,7 @@ create_blaat ()
         gtk_list_store_set (store, &iter,
                             0, pixbuf,
                             1, "gtk-stock-new",
+                           2, FALSE,
                             -1);
 
         pixbuf = gtk_widget_render_icon (cellview, GTK_STOCK_CLEAR,
@@ -159,6 +162,23 @@ create_blaat ()
         gtk_list_store_set (store, &iter,
                             0, pixbuf,
                             1, "gtk-stock-clear",
+                           2, FALSE,
+                            -1);
+
+        gtk_list_store_append (store, &iter);
+        gtk_list_store_set (store, &iter,
+                            0, NULL,
+                            1, "separator",
+                           2, TRUE,
+                            -1);
+
+        pixbuf = gtk_widget_render_icon (cellview, GTK_STOCK_OPEN,
+                                         GTK_ICON_SIZE_BUTTON, NULL);
+        gtk_list_store_append (store, &iter);
+        gtk_list_store_set (store, &iter,
+                            0, pixbuf,
+                            1, "gtk-stock-open",
+                           2, FALSE,
                             -1);
 
         gtk_widget_destroy (cellview);
@@ -196,8 +216,7 @@ set_sensitive (GtkCellLayout   *cell_layout,
 
   path = gtk_tree_model_get_path (tree_model, iter);
   indices = gtk_tree_path_get_indices (path);
-
-  sensitive = indices[0] % 2;
+  sensitive = indices[0] != 1;
   gtk_tree_path_free (path);
 
   g_object_set (cell, "sensitive", sensitive, NULL);
@@ -295,7 +314,9 @@ main (int argc, char **argv)
                                            renderer,
                                            set_sensitive,
                                            NULL, NULL);
-        gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 1);
+       gtk_combo_box_set_row_separator_column (GTK_COMBO_BOX (combobox), 2);
+                                               
+        gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 0);
 
 
         /* GtkComboBox (grid mode) */